package org.example

import com.alibaba.druid.pool.DruidDataSource
import com.wix.mysql.EmbeddedMysql
import com.wix.mysql.config.MysqldConfig
import org.apache.ibatis.mapping.Environment
import org.apache.ibatis.session.Configuration
import org.apache.ibatis.session.SqlSessionFactory
import org.apache.ibatis.session.SqlSessionFactoryBuilder
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory
import org.junit.After
import org.junit.Before
import org.junit.Test

import java.sql.Connection
import java.sql.DriverManager
import java.sql.ResultSet
import java.sql.Statement

import static com.wix.mysql.EmbeddedMysql.anEmbeddedMysql
import static com.wix.mysql.ScriptResolver.classPathScript
import static com.wix.mysql.ScriptResolver.classPathScripts
import static com.wix.mysql.config.Charset.UTF8
import static com.wix.mysql.config.MysqldConfig.aMysqldConfig
import static com.wix.mysql.distribution.Version.v5_7_latest
import static org.hamcrest.core.Is.is
import static org.junit.Assert.assertThat

class MyBatisDemoTests {

    private EmbeddedMysql mysqld

    private SqlSessionFactory sqlSessionFactory

    @Before
    void setup() {
        //mysqldConfigAndMultipleSchemas
        MysqldConfig config = aMysqldConfig(v5_7_latest)
                .withCharset(UTF8)
                .withPort(2215)
                .withUser("user", "password")
                .build()

        mysqld = anEmbeddedMysql(config)
                .addSchema("schema1", classPathScript("db/001_init.sql"))
                .addSchema("schema2", classPathScripts("db/*.sql"))
                .start()

        //init druid
        def dataSource = new DruidDataSource()
        dataSource.setUrl("jdbc:mysql://localhost:2215/schema1")
        dataSource.setUsername("user")
        dataSource.setPassword("password")

        //init mybatis
        def transactionFactory = new JdbcTransactionFactory()
        def configuration = new Configuration(new Environment("development", transactionFactory, dataSource))
        configuration.addMapper(T1Mapper.class)
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration)
    }

    @After
    void cleanup() {
        mysqld.stop() //optional, as there is a shutdown hook
    }

    @Test
    void ensureMysqlIsWorking() {
        def url = "jdbc:mysql://localhost:2215/schema1"
        final Connection conn = DriverManager.getConnection(url, "user", "password")
        final Statement statement = conn.createStatement()
        assertThat(statement.execute("SELECT * FROM t1;"), is(true))
        final ResultSet resultSet = statement.getResultSet()
        assertThat(resultSet.next(), is(true))
        assertThat(resultSet.getInt("col1"), is(10))
        assertThat(resultSet.getString("col2"), is("zzz"))
    }

    @Test
    void ensureMybatisIsWorking() {
        def session = sqlSessionFactory.openSession()
        def t1Mapper = session.getMapper(T1Mapper.class)

        def result1 = t1Mapper.selectOneByCol2("zzz")

        assert result1 instanceof Map
        assertThat(result1.col2, is("zzz"))
        assertThat(result1.col1, is(10))

        def result2 = t1Mapper.selectAllByCol2("zzz")

        assert result2 instanceof List
        assertThat(result2.size(), is(1))
        assert result2.first() instanceof Map
        assertThat(result2.first().col2, is("zzz"))
        assertThat(result2.first().col1, is(10))

        assert t1Mapper.insertT1(new T1(col1: 22, col2: "xxx"))

        def result3 = t1Mapper.findByCol2("xxx")

        assert result3 instanceof T1
        assertThat(result3.col2, is("xxx"))
        assertThat(result3.col1, is(22))

        assertThat(t1Mapper.insertT1Map(col1: 33, col2: "yyy"), is(1))

        def result4 = t1Mapper.findAllByCol2("yyy")

        assert result4 instanceof List
        assertThat(result4.size(), is(1))
        assert result4.first() instanceof T1
        assertThat(result4.first().col2, is("yyy"))
        assertThat(result4.first().col1, is(33))

        assert t1Mapper.updateT1ByCol1(new T1(col1: 22, col2: "AAA"))

        assertThat(t1Mapper.updateT1MapByCol1(col1: 33, col2: "BBB"), is(1))

        assertThat(t1Mapper.delete(33), is(1))

        session.close()
    }

    @Test
    void ensureMybatisWorkOnExternalConnection() {
        def connMapping = [
                "MyConn": DriverManager.getConnection("jdbc:mysql://localhost:2215/schema1", "user", "password")
        ]

        def session = sqlSessionFactory.openSession(connMapping.MyConn)

        assertThat(session.getMapper(T1Mapper.class).delete(22), is(0))

        assertThat(session.getConnection().toString(), is(connMapping.MyConn.toString()))

        session.close()
    }
}
